package com.hzw.saas.service.user.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.user.IUserInfoLogService;
import com.hzw.saas.api.user.bo.UserInfoLogBO;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.user.mapper.UserInfoLogMapper;
import com.hzw.saas.service.user.model.UserInfoLog;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author zzl
 * @since 05/27/2021
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserInfoLogServiceImpl extends ServiceImpl<UserInfoLogMapper, UserInfoLog> implements IUserInfoLogService, IService<UserInfoLog> {

    private static final UserInfoLogBO ONE_NOT_FOUND = null;

    private List<UserInfoLogBO> LIST_NOT_FOUND() {
        return new ArrayList<>();
    }

    @Override
    public boolean existLog(String pkey, String value) {
        if (StrUtil.isBlank(pkey))
            return false;
        int count = super.lambdaQuery()
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .count();
        return count > 0;
    }

    @Override
    public boolean existLog(String userId, String pkey, String value) {
        if (StrUtil.hasBlank(userId, pkey))
            return false;
        int count = super.lambdaQuery()
            .eq(UserInfoLog::getUserId, userId)
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .count();
        return count > 0;
    }

    @Override
    public boolean existLogExclude(String excludedUserId, String pkey, String value) {
        Integer count = super.lambdaQuery()
            .ne(Objects.nonNull(excludedUserId), UserInfoLog::getUserId, excludedUserId)
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .count();
        return count > 0;
    }

    @Override
    public UserInfoLogBO getLog(String userId, String pkey, String value) {
        if (StrUtil.hasBlank(userId, pkey))
            return ONE_NOT_FOUND;
        List<UserInfoLog> list = super.lambdaQuery()
            .eq(UserInfoLog::getUserId, userId)
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .orderByAsc(UserInfoLog::getEnableTime)
            .list();
        if (list.isEmpty())
            return ONE_NOT_FOUND;
        return MapperUtil.nf().map(list.get(0), UserInfoLogBO.class);
    }

    @Override
    public List<UserInfoLogBO> listLogsByKey(String pkey, String value) {
        if (StrUtil.isBlank(pkey))
            return LIST_NOT_FOUND();
        List<UserInfoLog> list = super.lambdaQuery()
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .orderByAsc(UserInfoLog::getEnableTime)
            .list();
        return MapperUtil.nf().mapAsList(list, UserInfoLogBO.class);
    }

    @Override
    public List<UserInfoLogBO> listLogsByUser(String userId, String pkey) {
        if (StrUtil.hasBlank(userId, pkey))
            return LIST_NOT_FOUND();
        List<UserInfoLog> list = super.lambdaQuery()
            .eq(UserInfoLog::getUserId, userId)
            .eq(UserInfoLog::getPKey, pkey)
            .orderByAsc(UserInfoLog::getEnableTime)
            .list();
        return MapperUtil.nf().mapAsList(list, UserInfoLogBO.class);
    }

    @Override
    public List<UserInfoLogBO> listLogsByUser(String userId) {
        if (StrUtil.isBlank(userId))
            return LIST_NOT_FOUND();
        List<UserInfoLog> list = super.lambdaQuery()
            .eq(UserInfoLog::getUserId, userId)
            .orderByAsc(UserInfoLog::getPKey)
            .orderByAsc(UserInfoLog::getEnableTime)
            .list();
        return MapperUtil.nf().mapAsList(list, UserInfoLogBO.class);
    }

    @Override
    public UserInfoLogBO addLog(UserInfoLogBO log2Add) {
        if (Objects.isNull(log2Add))
            return null;
        this.initLog2Add(log2Add);
        UserInfoLog entity = MapperUtil.nf().map(log2Add, UserInfoLog.class);
        this.disableLog(log2Add.getUserId(), log2Add.getPKey());
        super.save(entity);
        return log2Add;
    }

    @Override
    public List<UserInfoLogBO> addLogs(List<UserInfoLogBO> logs2Add) {
        if (Objects.isNull(logs2Add))
            return null;
        if (CollectionUtil.isEmpty(logs2Add))
            return logs2Add;
        for (UserInfoLogBO log2Add : logs2Add) {
            this.addLog(log2Add);
        }
        return logs2Add;
    }

    @Override
    public boolean disableLog(String userId, String pkey, String value) {
        if (StrUtil.hasBlank(userId, pkey))
            return false;
        return super.lambdaUpdate()
            .eq(UserInfoLog::getUserId, userId)
            .eq(UserInfoLog::getPKey, pkey)
            .eq(UserInfoLog::getPValue, value)
            .set(UserInfoLog::getDisableTime, new Date())
            .update();
    }

    @Override
    public boolean disableLog(String userId, String pkey) {
        if (StrUtil.hasBlank(userId, pkey))
            return false;
        return super.lambdaUpdate()
            .eq(UserInfoLog::getUserId, userId)
            .eq(UserInfoLog::getPKey, pkey)
            .isNull(UserInfoLog::getDisableTime)
            .set(UserInfoLog::getDisableTime, new Date())
            .update();
    }

    private void initLog2Add(UserInfoLogBO log2Add) {
        if (StrUtil.isBlank(log2Add.getPid()))
            log2Add.setPid(SnowFlakeUtil.nextIdStr());
        if (Objects.isNull(log2Add.getEnableTime()))
            log2Add.setEnableTime(new Date());
    }
}
